﻿using System.Security.Claims;
using AGooday.AgChat.Api.Data;
using AGooday.AgChat.Api.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace AGooday.AgChat.Api.Controllers
{// Controllers/MessagesController.cs
    [ApiController]
    [Route("api/[controller]")]
    [Authorize]
    public class MessagesController : ControllerBase
    {
        private readonly ApplicationDbContext _context;

        public MessagesController(ApplicationDbContext context)
        {
            _context = context;
        }

        [HttpGet("private/{friendId}")]
        public async Task<IActionResult> GetPrivateMessages(int friendId, [FromQuery] int page = 1, [FromQuery] int pageSize = 20)
        {
            var userId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);

            // Check if users are friends
            var isFriend = await _context.Friendships
                .AnyAsync(f =>
                    (f.UserId == userId && f.FriendId == friendId && f.Status == "accepted") ||
                    (f.UserId == friendId && f.FriendId == userId && f.Status == "accepted"));

            if (!isFriend)
            {
                return Forbid("You are not friends with this user");
            }

            var messages = await _context.Messages
                .Where(m =>
                    (m.SenderId == userId && m.ReceiverId == friendId) ||
                    (m.SenderId == friendId && m.ReceiverId == userId))
                .Include(m => m.Sender)
                .OrderByDescending(m => m.SentAt)
                .Skip((page - 1) * pageSize)
                .Take(pageSize)
                .Select(m => new
                {
                    m.Id,
                    m.Content,
                    m.MessageType,
                    m.SentAt,
                    m.IsRead,
                    Sender = new
                    {
                        m.Sender.Id,
                        m.Sender.Username,
                        m.Sender.Avatar
                    }
                })
                .ToListAsync();
            messages.Reverse();
            return Ok(messages);
        }

        [HttpGet("group/{groupId}")]
        public async Task<IActionResult> GetGroupMessages(int groupId, [FromQuery] int page = 1, [FromQuery] int pageSize = 20)
        {
            var userId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);

            // Check if user is member of the group
            var isMember = await _context.GroupMembers
                .AnyAsync(gm => gm.GroupId == groupId && gm.UserId == userId);

            if (!isMember)
            {
                return Forbid("You are not a member of this group");
            }

            var messages = await _context.Messages
                .Where(m => m.GroupId == groupId)
                .Include(m => m.Sender)
                .OrderByDescending(m => m.SentAt)
                .Skip((page - 1) * pageSize)
                .Take(pageSize)
                .Select(m => new
                {
                    m.Id,
                    m.Content,
                    m.MessageType,
                    m.SentAt,
                    m.IsRead,
                    Sender = new
                    {
                        m.Sender.Id,
                        m.Sender.Username,
                        m.Sender.Avatar
                    }
                })
                .ToListAsync();
            messages.Reverse();
            return Ok(messages);
        }

        [HttpPost("read/{messageId}")]
        public async Task<IActionResult> MarkAsRead(int messageId)
        {
            var userId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);

            var message = await _context.Messages.FindAsync(messageId);

            if (message == null)
            {
                return NotFound("Message not found");
            }

            if (message.ReceiverId != userId &&
                (!message.GroupId.HasValue ||
                 !await _context.GroupMembers.AnyAsync(gm => gm.GroupId == message.GroupId && gm.UserId == userId)))
            {
                return Forbid("You cannot mark this message as read");
            }

            message.IsRead = true;
            await _context.SaveChangesAsync();

            return Ok("Message marked as read");
        }

        [HttpPost("read/all")]
        public async Task<IActionResult> MarkAllAsRead([FromQuery] int? friendId, [FromQuery] int? groupId)
        {
            var userId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);

            IQueryable<Message> query = _context.Messages;

            if (friendId.HasValue)
            {
                query = query.Where(m =>
                    ((m.SenderId == friendId && m.ReceiverId == userId) ||
                     (m.SenderId == userId && m.ReceiverId == friendId)) &&
                    !m.IsRead);
            }
            else if (groupId.HasValue)
            {
                query = query.Where(m =>
                    m.GroupId == groupId &&
                    m.SenderId != userId &&
                    !m.IsRead);
            }
            else
            {
                return BadRequest("Either friendId or groupId must be specified");
            }

            var messages = await query.ToListAsync();

            foreach (var message in messages)
            {
                message.IsRead = true;
            }

            await _context.SaveChangesAsync();

            return Ok("All messages marked as read");
        }
    }
}
